﻿using FB.Membership.Principal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

namespace FB.Membership.Annotations
{
    public class ApiAuthorizeOnlyAttribute : AuthorizeAttribute//, System.Web.Http.Filters.IFilter
    {
         readonly IRolesService _rolesService;
         readonly IUserService _userService;
         string[] _rolesSplit;
         string[] _usersSplit;

        public object Permission { get; set; }

        public ApiAuthorizeOnlyAttribute()
            : this(new AspNetMembershipProviderWrapper(), new AspNetRoleProviderWrapper())
        {
        }

        public ApiAuthorizeOnlyAttribute(IUserService userService, IRolesService rolesService)
		{
			_userService = userService;
			_rolesService = rolesService;
		}


        protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var result = false;

            if (actionContext == null)
                throw new ArgumentNullException("actionContext");

            var user = HttpContext.Current.User;
            if (!user.Identity.IsAuthenticated)
                return false;

            #region checking services list

            var fbi = user.Identity as FBIdentity;
            if (null == fbi)
                return false;
            else
            {
                var serviceList = _userService.GetService(user.Identity.Name); 
                if (!_userService.HasService(FB.Helpers.AppSettingsBase.AppKey.ToString(), user.Identity.Name, serviceList))
                    return false;
            }

            #endregion


            #region checking for authenticated user

            if (null == PermissionManager.PermissionSession)
            {
                // refresh permissions and roles
                RefreshRoleAndPermission();
            }

            
            if (!string.IsNullOrEmpty(Users)) _usersSplit = SplitString(Users);
            if (!string.IsNullOrEmpty(Roles)) _rolesSplit = SplitString(Roles);


            if (null != _usersSplit && _usersSplit.Any()
                && _usersSplit.Contains(user.Identity.Name, StringComparer.InvariantCultureIgnoreCase))
            {
                result = true;
            }
            else if (null != _rolesSplit &&
               _rolesSplit.Any() && _rolesService.Enabled &&
               _rolesSplit.Any(user.IsInRole))
            {
                result = true;
            }
            else if (null != Permission && (user is FBPrincipal) &&
               this.Permission.GetType().IsEnum &&
               ((FBPrincipal)user).HasFlag(this.Permission))
            {
                result = true;
            }
            else if (null == _rolesSplit && null == _usersSplit && null == Permission)
            {
                result = true;
            }

            #endregion 


            return base.IsAuthorized(actionContext) && result;
        }


        #region Private

        private static string[] SplitString(string original)
        {
            if (String.IsNullOrEmpty(original))
                return new string[0];

            var split = from piece in original.Split(',')
                        let trimmed = piece.Trim()
                        where !String.IsNullOrEmpty(trimmed)
                        select trimmed;
            return split.ToArray();
        }

        void RefreshRoleAndPermission()
        {
            var user = HttpContext.Current.User;
            if (user.Identity.IsAuthenticated)
            {
                var membership = System.Web.Security.Membership.GetUser(user.Identity.Name);
                PermissionManager.PermissionSession = PermissionManager.GetUserPermissions(membership);
                AspNetRoleProviderWrapper.RoleSession = System.Web.Security.Roles.GetRolesForUser(user.Identity.Name);
            }
        }

        #endregion

    }
    
}
